package com.we.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class HiveBigDecimal {
    public static final int MAX_PRECISION = 38;
    public static final int MAX_SCALE = 38;

    private static BigDecimal trim(BigDecimal d) {
        if (d.compareTo(BigDecimal.ZERO) == 0) {
            // Special case for 0, because java doesn't strip zeros correctly on that number.
            d = BigDecimal.ZERO;
        } else {
            d = d.stripTrailingZeros();
            if (d.scale() < 0) {
                // no negative scale decimals
                d = d.setScale(0);
            }
        }
        return d;
    }

    private static BigDecimal normalize(BigDecimal bd, boolean allowRounding) {
        if (bd == null) {
            return null;
        }

        bd = trim(bd);

        int intDigits = bd.precision() - bd.scale();

        if (intDigits > MAX_PRECISION) {
            return null;
        }

        int maxScale = Math.min(MAX_SCALE, Math.min(MAX_PRECISION - intDigits, bd.scale()));
        if (bd.scale() > maxScale) {
            if (allowRounding) {
                bd = bd.setScale(maxScale, RoundingMode.HALF_UP);
                // Trimming is again necessary, because rounding may introduce new trailing 0's.
                bd = trim(bd);
            } else {
                bd = null;
            }
        }
        return bd;
    }

    public static BigDecimal create(BigDecimal b, boolean allowRounding) {
        BigDecimal bd = normalize(b, allowRounding);
        return bd == null ? null : bd;
    }

    public static BigDecimal divide(BigDecimal bd, BigDecimal dec) {
        return create(bd.divide(dec, MAX_SCALE, RoundingMode.HALF_UP), true);
    }
}
